package com.security.manage.search.controller;

import com.alibaba.fastjson.JSONObject;
import com.security.manage.search.model.*;
import com.security.manage.search.repository.RegistryWarnRepository;
import com.security.manage.search.repository.SoftChangeRepository;
import com.security.manage.search.repository.WarnInfoRepository;
import com.security.manage.search.service.UserMicroService;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.LongStream;

@RestController
public class IndexController {

    @Resource
    private RegistryWarnRepository registryWarnRepository;

    @Resource
    private SoftChangeRepository softChangeRepository;

    @Resource
    private WarnInfoRepository warnInfoRepository;

    @Resource
    private UserMicroService userMicroService;

    @GetMapping("/registry/warn")
    public ResData registryWarn(ReqDto dto) {
        Integer page = dto.getPage();
        Integer size = dto.getSize();
        Sort sort = Sort.by(Sort.Direction.DESC, "secondTime");
        PageRequest of = PageRequest.of(page,size, sort);
        Specification<RegistryWarn> specification = new Specification<RegistryWarn>() {
            @Override
            public Predicate toPredicate(Root<RegistryWarn> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();

                if (StringUtils.isNotEmpty(dto.getDeptIds())) {
                    CriteriaBuilder.In<Long> in = criteriaBuilder.in(root.get("deptId").as(Long.class));
                    for (String id : dto.getDeptIds().split(",")) {
                        in.value(Long.parseLong(id));
                    }
                    predicateList.add(in);
                }

                if (dto.getUserId() != null && dto.getUserId() != 0L) {
                    predicateList.add(criteriaBuilder.equal(root.get("userId").as(Long.class), dto.getUserId()));
                }

                Predicate[] pre = new Predicate[predicateList.size()];
                pre = predicateList.toArray(pre);
                return criteriaQuery.where(pre).getRestriction();
            }
        };
        Page<RegistryWarn> all = registryWarnRepository.findAll(specification, of);
        String data = userMicroService.listAll();
        JSONObject jsonObject = JSONObject.parseObject(data);
        JSONObject users = jsonObject.getJSONObject("users");
        JSONObject depts = jsonObject.getJSONObject("depts");
        List<Map<String,Object>> resultList = new ArrayList<>();
        all.get().forEach(log -> {
            Map<String,Object> map = objectToMap(log);
            map.put("userName",users.get(map.get("userId")));
            map.put("deptName",depts.get(map.get("deptId")));
            resultList.add(map);
        });
        Map<String, Object> map = new HashMap<>();
        map.put("total", all.getTotalElements());
        map.put("data", resultList);
        return new ResData(1, "获取成功", map);

    }

    @GetMapping("/soft/change")
    public ResData softChange(ReqDto dto) {
        Integer page = dto.getPage();
        Integer size = dto.getSize();
        Sort sort = Sort.by(Sort.Direction.DESC, "secondTime");
        PageRequest of = PageRequest.of(page, size, sort);
        Specification<SoftChange> specification = new Specification<SoftChange>() {
            @Override
            public Predicate toPredicate(Root<SoftChange> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();

                if (StringUtils.isNotEmpty(dto.getDeptIds())) {
                    CriteriaBuilder.In<Long> in = criteriaBuilder.in(root.get("deptId").as(Long.class));
                    for (String id : dto.getDeptIds().split(",")) {
                        in.value(Long.parseLong(id));
                    }
                    predicateList.add(in);
                }

                if (dto.getUserId() != null && dto.getUserId() != 0L) {
                    predicateList.add(criteriaBuilder.equal(root.get("userId").as(Long.class), dto.getUserId()));
                }

                Predicate[] pre = new Predicate[predicateList.size()];
                pre = predicateList.toArray(pre);
                return criteriaQuery.where(pre).getRestriction();
            }
        };
        Page<SoftChange> all = softChangeRepository.findAll(specification, of);
        String data = userMicroService.listAll();
        JSONObject jsonObject = JSONObject.parseObject(data);
        JSONObject users = jsonObject.getJSONObject("users");
        JSONObject depts = jsonObject.getJSONObject("depts");
        List<Map<String,Object>> resultList = new ArrayList<>();
        all.get().forEach(log -> {
            Map<String,Object> map = objectToMap(log);
            map.put("userName",users.get(map.get("userId")));
            map.put("deptName",depts.get(map.get("deptId")));
            resultList.add(map);
        });
        Map<String, Object> map = new HashMap<>();
        map.put("total", all.getTotalElements());
        map.put("data", resultList);
        return new ResData(1, "获取成功", map);
    }

    @GetMapping("usbKey/statics")
    public ResData usbKeyStatics(String deptIds){

        List<Long> ids = Arrays.asList(deptIds.split(",")).stream().map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
        List<WarnInfo> infos = warnInfoRepository.findByDeptIdIn(ids);
        long allExcepNum = infos.stream().mapToLong(WarnInfo::getUserId).distinct().count();
        String res = userMicroService.getManageBoundUsbKey(deptIds, 1);
        JSONObject parse = JSONObject.parseObject(res);
        long totalNum = parse.getLong("data");

        long terminalNum = infos.stream().filter(warnInfo -> warnInfo.getWarnType() == 2).mapToLong(WarnInfo::getUserId).distinct().count();
        List<Map<String,Object>> list = new ArrayList<>();
        Map<String,Object> map = new HashMap<>();
        map.put("name","正常");
        map.put("value",totalNum-allExcepNum);
        Map<String,Object> map2 = new HashMap<>();
        map2.put("name","异常");
        map2.put("value",allExcepNum);
        list.add(map);
        list.add(map2);
        List<Map<String,Object>> list2 = new ArrayList<>();
        Map<String,Object> map3 = new HashMap<>();
        map3.put("name","正常");
        map3.put("value",totalNum-terminalNum);
        Map<String,Object> map4 = new HashMap<>();
        map4.put("name","异常");
        map4.put("value",terminalNum);
        list2.add(map3);
        list2.add(map4);

        List<Map<String,Object>> list3 = new ArrayList<>();
        Map<String,Object> map5 = new HashMap<>();
        map5.put("name","网络");
        map5.put("value",allExcepNum-terminalNum);
        Map<String,Object> map6 = new HashMap<>();
        map6.put("name","注册表");
        map6.put("value",terminalNum);
        list3.add(map5);
        list3.add(map6);

        Map<String,Object> result = new HashMap<>();
        result.put("data1",list);
        result.put("data2",list2);
        result.put("data3",list3);

        return new ResData(1,"获取成功",result);
    }

    @GetMapping("/warn/details")
    public ResData warnDetails(SearchDto dto){
        if (StringUtils.isEmpty(dto.getDeptIds())){
            return new ResData(0,"参数异常",null);
        }
        int page = dto.getPage();
        int size = dto.getSize();
        Sort sort = Sort.by(Sort.Direction.DESC, "createTime");
        PageRequest of = PageRequest.of(page, size, sort);
        Specification<WarnInfo> specification = new Specification<WarnInfo>() {
            @Override
            public Predicate toPredicate(Root<WarnInfo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicateList = new ArrayList<>();

                CriteriaBuilder.In<Long> in = criteriaBuilder.in(root.get("deptId").as(Long.class));
                for (String id : dto.getDeptIds().split(",")) {
                    in.value(Long.parseLong(id));
                }
                predicateList.add(in);

                Predicate[] pre = new Predicate[predicateList.size()];
                pre = predicateList.toArray(pre);
                return criteriaQuery.where(pre).getRestriction();
            }
        };

        Page<WarnInfo> all = warnInfoRepository.findAll(specification, of);
        String data = userMicroService.listAll();
        JSONObject jsonObject = JSONObject.parseObject(data);
        JSONObject users = jsonObject.getJSONObject("users");
        JSONObject depts = jsonObject.getJSONObject("depts");

        List<Map<String,Object>> result = new ArrayList<>();
        all.get().forEach(info -> {
            Map<String,Object> map = objectToMap(info);
            map.put("logName",dto.getType());
            map.put("userName",users.get(map.get("userId")));
            map.put("deptName",depts.get(map.get("deptId")));
            result.add(map);
        });
        Map<String, Object> map = new HashMap<>();
        map.put("count", all.getTotalElements());
        map.put("data", result);
        return new ResData(1, "获取成功", map);

    }

    public Map<String, Object> objectToMap(Object obj) {
        if (obj == null) {
            return null;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Field[] declaredFields = obj.getClass().getDeclaredFields();
            for (Field field : declaredFields) {
                field.setAccessible(true);
                map.put(field.getName(), field.get(obj));
            }
        }catch (Exception e){

        }

        return map;
    }

}
